import React, { useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { ErrorMessage } from '@hookform/error-message';
import {
  Box,
  FormStatusMessage,
  Grid,
  GridItem,
  Input,
  MainButton,
  makeToast,
  NotificationBanner,
  Select,
  Text,
} from '@nova-hf/ui';
import StepWrapper from 'beta/containers/layout/StepWrapper';
import Authentication from 'beta/store/authentication';
import { IContext } from 'beta/typings/context';
import { serviceColorMap } from 'beta/utils/helpers';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import {
  AddDiscountInput,
  ContractStatus,
  useAddContractDiscountMutation,
  useContractAvailableOffersQuery,
  useContractsQuery,
  useServiceQuery,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

type AfslatturProps = {
  customerId: string;
  serviceId: string;
  authentication?: Authentication;
};

const Afslattur = ({ customerId, serviceId, authentication }: AfslatturProps) => {
  const { t } = useTranslation('service');
  const isStaff = authentication?.isStaff;
  const router = useRouter();

  const { data, error, loading } = useServiceQuery({
    variables: {
      serviceId,
    },
    skip: !serviceId,
  });
  const {
    data: contractData,
    loading: contractLoading,
    error: contractError,
  } = useContractsQuery({
    variables: {
      input: {
        serviceId,
        customerId,
      },
    },
    skip: !serviceId || !customerId,
  });
  const contract = contractData?.contracts.contracts.find(
    (contract) =>
      contract.status === ContractStatus.Active || contract.status === ContractStatus.Pending,
  );

  const {
    data: offerData,
    loading: offerLoading,
    error: offerError,
  } = useContractAvailableOffersQuery({
    variables: {
      input: {
        id: contract?.id ?? '',
      },
    },
    skip: !contract?.id,
  });

  const [addDiscount, { loading: addDiscountLoading }] = useAddContractDiscountMutation({
    onCompleted(data) {
      if (data?.addContractDiscount?.message) {
        makeToast.success(t('discounts.success'), '');
        router.push(`/beta/${customerId}/thjonustur/${serviceId}`);
      }
    },
    onError(error) {
      if (error) {
        makeToast.danger(t('discounts.failure'), error.message);
      }
    },
  });

  const color = serviceColorMap(data?.service?.type);
  const offers = offerData?.contractAvailableOffers;
  const [isTypeSelected, setIsTypeSelected] = useState(false);
  const [isReasonSelected, setIsReasonSelected] = useState(false);
  const {
    control,
    watch,
    handleSubmit,
    setValue,
    formState: { isValid },
  } = useForm<AddDiscountInput>({
    defaultValues: {
      description: '',
      offerId: '',
      offerReasonId: '',
    },
    delayError: 500,
    mode: 'onChange',
  });

  const onSubmit = (formData: AddDiscountInput) => {
    addDiscount({
      variables: {
        input: {
          id: contract?.id ?? '',
          offerId: formData.offerId,
          offerReasonId: formData.offerReasonId,
          description: formData.description,
        },
      },
    });
  };

  const loadingCheck = loading || addDiscountLoading || offerLoading || contractLoading;
  const { offerId } = watch();

  return (
    <StepWrapper
      color={color}
      returnUrl={`/beta/${customerId}/thjonustur/${serviceId}`}
      title={data?.service?.user?.name ?? t('discounts.discount')}
      subTitle={data?.service?.name ?? ''}
      icon="novaLogo"
    >
      {offers && offers.length > 0 && isStaff ? (
        <Box renderAs="form" onSubmit={handleSubmit(onSubmit)}>
          <Grid gridTemplate={{ sm: 4, md: 8 }}>
            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Box marginBottom={3} display="flex" flexDirection="column">
                <Text color="black100" variant="h6" marginTop={5}>
                  {t('discounts.title')}
                </Text>
                <Text marginTop={3} color="black100" variant="pMediumRegular">
                  {t('discounts.subTitle')}
                </Text>
              </Box>
            </GridItem>

            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Controller
                name="offerId"
                control={control}
                rules={{
                  required: true,
                }}
                render={({ field, formState: { errors } }) => {
                  const { name } = field;
                  return (
                    <Box>
                      <Select
                        id="type"
                        label={t('discounts.type')}
                        name={name}
                        isBold={isTypeSelected}
                        onChange={(e) => {
                          const selectedOfferId = e.target.value;
                          setValue('offerId', selectedOfferId);
                          setIsTypeSelected(!!selectedOfferId);
                        }}
                        disabled={loadingCheck}
                        required
                      >
                        <option value="" hidden>
                          {t('discounts.typePlaceholder')}
                        </option>
                        {offers?.map((offer, index) => {
                          return (
                            <option key={index} value={offer?.id}>
                              {offer?.name}
                            </option>
                          );
                        })}
                      </Select>
                      <ErrorMessage
                        errors={errors}
                        name={name}
                        render={() => (
                          <FormStatusMessage message={t('discounts.typeError')} status="error" />
                        )}
                      />
                    </Box>
                  );
                }}
              />
            </GridItem>

            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Controller
                name="offerReasonId"
                control={control}
                rules={{
                  required: true,
                }}
                render={({ field, formState: { errors } }) => {
                  const { name } = field;
                  return (
                    <Box>
                      <Select
                        id="reason"
                        label={t('discounts.reason')}
                        name={name}
                        isBold={isReasonSelected}
                        onChange={(e) => {
                          const selectedReason = e.target.value;
                          setValue('offerReasonId', selectedReason);
                          setIsReasonSelected(!!selectedReason);
                        }}
                        disabled={loadingCheck}
                        required
                      >
                        <option value="" hidden>
                          {t('discounts.reasonPlaceHolder')}
                        </option>
                        {offers
                          ?.find((offer) => offer.id === offerId)
                          ?.reasons?.map((reason, index) => {
                            return (
                              <option key={index} value={reason?.id}>
                                {reason?.title}
                              </option>
                            );
                          })}
                      </Select>
                      <ErrorMessage
                        errors={errors}
                        name={name}
                        render={() => (
                          <FormStatusMessage message={t('discounts.reasonError')} status="error" />
                        )}
                      />
                    </Box>
                  );
                }}
              />
            </GridItem>

            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Controller
                name="description"
                control={control}
                rules={{
                  required: false,
                  max: {
                    value: 250,
                    message: t('discounts.toLong'),
                  },
                }}
                render={({ field, formState: { errors } }) => {
                  const { name } = field;
                  return (
                    <Box>
                      <Input
                        id="description"
                        label={t('discounts.description')}
                        isBold={false}
                        {...field}
                      />
                      <ErrorMessage
                        errors={errors}
                        name={name}
                        render={() => (
                          <FormStatusMessage message={t('discounts.typeError')} status="error" />
                        )}
                      />
                    </Box>
                  );
                }}
              />
            </GridItem>
            {(error || contractError || offerError || !data) && (
              <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
                <FormStatusMessage message={t('discounts.error')} status="error" />
              </GridItem>
            )}
            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Box
                display="flex"
                marginTop={6}
                justifyContent="flex-end"
                flexDirection={{ sm: 'column', md: 'row' }}
              >
                <Box display="flex" width={{ sm: '100%', md: '4/12' }}>
                  <MainButton
                    text={t('discounts.activate')}
                    colorScheme={color}
                    isDisabled={!isValid}
                    isSubmitButton
                    isLoading={loadingCheck}
                  />
                </Box>
              </Box>
            </GridItem>
          </Grid>
        </Box>
      ) : (
        <NotificationBanner
          description={t('discounts.noDiscount')}
          eyebrowText={t('discounts.discount')}
          icon="tag"
          mainButtonColored={{
            icon: 'longArrowRight',
            text: t('discounts.back'),
            color: color,
            onClick: () => {
              router.push(`/beta/${customerId}/thjonustur/${serviceId}`);
            },
          }}
          title={t('discounts.noDiscountTitle')}
        />
      )}
    </StepWrapper>
  );
};

Afslattur.getInitialProps = ({ pathname, query }: IContext) => {
  return {
    pathname,
    customerId: query.customerId,
    serviceId: query.serviceId,
    namespacesRequired: ['service'],
  };
};

export default inject('authentication', 'steps', 'ui')(observer(Afslattur));
